#include "ZerglingBlood.h"
using namespace BWAPI;

void ZerglingBlood::onStart()
{
	//Broodwar->sendText("Hello world!");
	//Broodwar->printf("The map is %s, a %d player map",Broodwar->mapName().c_str(),Broodwar->getStartLocations().size());
	// Enable some cheat flags
	Broodwar->enableFlag(Flag::UserInput);
	// Uncomment to enable complete map information
	//Broodwar->enableFlag(Flag::CompleteMapInformation);

	//Initialize game state variables
	show_bullets=false;
	show_visibility_data=false;
	set_scouts = 0;

	show_chokes = false;
	show_unit_pos = false;
	show_unit_type_id = false;
	show_squad_circle = false;
	show_dship_pos = false;

	game_state = STARTUP;
	spawn_location = BADJ;
	squad_state = WAITING;
	attack_location = NONE;

	//Get dropship and drone unit pointers
	std::set<Unit*> myUnits = Broodwar->self()->getUnits();
	int id;
	for(std::set<Unit*>::iterator i = myUnits.begin(); i != myUnits.end(); i++)
	{
		id = (*i)->getType().getID();
		
		if(id == ZBDROPSHIP)
			dropShip = (*i);
		else if(id == ZBDRONE)
			drone = (*i);
	}
	//Set stats for players
	std::set<Player*> players = Broodwar->getPlayers();
	for(std::set<Player* >::iterator it = players.begin(); it != players.end(); ++it)
	{
		Color pColor = (*it)->getColor();
		if(isGamePlayer(pColor))
		{
			stats[pColor].zergling_count = 0;
			stats[pColor].credit_count = 0;
			stats[pColor].kill_count = 0;
			stats[pColor].probe_count = 0;
			stats[pColor].spawn_type = BSPAWN;
			stats[pColor].spawn_location = getBase((*it));
			stats[pColor].dropshipPos = stats[pColor].spawn_location;
		}
	}

	//Get drone close to drop ship spawning beacon
	drone->move(Position(DROPSHIPX,DROPSHIPY));
	frame_sec = Broodwar->getFrameCount();

	//Move Dropship to Center
	dropShip->move(Position(CENTERX, CENTERY));

	//Initialize Managers
	ship_manager = DropShipManager(dropShip,Broodwar);
	attack_manager = ZBAttackManager(Broodwar);
	hero_manager = ZBHeroManager();
}


void ZerglingBlood::onFrame()
{
	// if a ling is damaged, causes it to burrow. Doesn't work that well.
	checkHealth();

	if (show_visibility_data)
		drawVisibilityData();

	if (show_bullets)
		drawBullets();

	if (show_chokes)
		drawChokes();

	if (show_unit_pos)
		drawUnitPos();

	if (show_unit_type_id)
		drawUnitID();

	if (show_squad_circle)
		drawSquadCircle();

	if (show_dship_pos)
		attack_manager.drawDShipPosition();

	if (spawn_location != SWAITING || spawn_location != BWAITING || spawn_location != DWAITING)
		checkSwap();

	if (squad_state == MOVING || squad_state == REGROUPING)
		checkMove();

	if (squad_state == ATTACKING)
		checkAttack();

	if (squad_state == SURROUNDING)
		checkSurround();
	
	if(frame_sec <= Broodwar->getFrameCount() - 10)
	{
		updateStats();
		frame_sec = Broodwar->getFrameCount();
		if (set_scouts < 7)
			checkScouts();
		ship_manager.shipSlowFrame();
	}
	
	ship_manager.shipFastFrame();

	ZerglingController::getInstance().upkeep();

	drawStats();

	switch(game_state)
	{
		case STARTUP:
			if(dropShip->getPosition() == Position(CENTERX, CENTERY))
			{
				Broodwar->printf("Dropship in position");
				swapSpawn(DSHIP);
				game_state = PREMIDGAME;
			}
			break;
		case PREMIDGAME:
			if(spawn_location == DWAITING)
			{
				Broodwar->printf("We are spawning in the middle");
				game_state = MIDGAME;
			}
			break;
		case MIDGAME:
			if(squad_state != SURROUNDING)
			{
				std::set<Player *> players = Broodwar->getPlayers();
				int players_found = 0;
				for(std::set<Player *>::iterator it = players.begin(); it != players.end(); ++it)
				{
					if(isGamePlayer((*it)->getColor()))
					{
						++players_found;
					}
				}
				if(players_found < 2)
				{
					Broodwar->printf("\x19""No one to surround");
					squad_state = SURROUNDING;
					return;
				}

				int base = attack_manager.whichBase(stats[Broodwar->enemy()->getColor()].spawn_location);
				switch(base)
				{
					case BRED:
						surround(Position(CHOKEREDCX, CHOKEREDCY), CHOKEREDRAD);
						break;
					case BBLUE:
						surround(Position(CHOKEBLUECX, CHOKEBLUECY), CHOKEBLUERAD);
						break;
					case BTEAL:
						surround(Position(CHOKETEALCX, CHOKETEALCY), CHOKETEALRAD);
						break;
					case BPURPLE:
						surround(Position(CHOKEPURPLECX, CHOKEPURPLECY), CHOKEREDRAD);
						break;
					case BORANGE:
						surround(Position(CHOKEORANGECX, CHOKEORANGECY), CHOKEORANGERAD);
						break;
					case BBROWN:
						surround(Position(CHOKEBROWNCX, CHOKEBROWNCY), CHOKEBROWNRAD);
						break;
				}
			}
			break;
	}
}

void ZerglingBlood::onSendText(std::string text)
{
	if (text=="/show bullets")
	{
		show_bullets = !show_bullets;
	} else if (text=="/show players")
	{
		showPlayers();
	} else if (text=="/show forces")
	{
		showForces();
	} else if (text=="/show visibility")
	{
		show_visibility_data=!show_visibility_data;
	} else if (text=="/chokes")
	{
		show_chokes = ! show_chokes;
	} else if (text=="/pos")
	{
		show_unit_pos = !show_unit_pos;
		show_unit_type_id = false;
	} else if(text=="/typeid")
	{
		show_unit_type_id = !show_unit_type_id;
		show_unit_pos = false;
	} else if(text =="/base")
	{
		swapSpawn(BASE);
	} else if(text =="/sship")
	{
		swapSpawn(SSHIP);
	} else if(text == "/dship")
	{
		swapSpawn(DSHIP);
	} else if(text == "/spawn")
	{
		Broodwar->printf("\x19Spawn: %d", spawn_location);
	}else if(text =="/avail")
	{
		//Test ling sets
		for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
			(*it)->attackMove(Position(1400,2400));
	} else if(text =="/positions")
	{
		Broodwar->printf("\x19Players: %d",stats.size());
		for(std::map< BWAPI::Color, struct playerStats>::iterator it = stats.begin(); it != stats.end(); ++ it)
		{
			Broodwar->printf("\x19Posx: %d Posy: %d",(*it).second.spawn_location.x(), (*it).second.spawn_location.y());
		}
	} else if(text =="/middle")
	{
		groupMove(Position(CENTERX, CENTERY));
	} else if(text == "/speedup")
	{
		Broodwar->setLocalSpeed(0);
	} else if(text == "/slowdown")
	{
		Broodwar->setLocalSpeed(-1);
	} else if(text == "/burrow")
	{
		for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
			(*it)->burrow();
	} else if(text == "/unburrow")
	{
		for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
			(*it)->unburrow();
	} else if(text =="/stats")
	{
		printStats();
	} else if(text =="/sscout")
	{
		ship_manager.scoutBases();
	} else if(text =="/harhar")
	{
		for(std::set<Unit* >::const_iterator it = drone->getPlayer()->getUnits().begin() ; it != drone->getPlayer()->getUnits().end(); ++ it)
		{
			if((*it)->getType().getID() == ZBFIREBAT || (*it)->getType().getID() == ZBGHOST || (*it)->getType().getID() == ZBKERRIGAN)
			{
				fb = (*it);
				break;
			}
		}
		ship_manager.harass(fb);
	}else if(text == "/attack")
	{
		startAttack(stats[Broodwar->enemy()->getColor()].spawn_location);
	} else if(text == "/surround")
	{
		surround(Position(CHOKEBLUECX, CHOKEBLUECY), CHOKEBLUERAD);
	} else if (text == "/ctlattack")
	{
		std::set<BWAPI::Unit*> controllerAttackers;
		for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
		{
			controllerAttackers.insert(*it);
			avaiLings.erase(*it);
		}
		ZerglingController::getInstance().attack(controllerAttackers, BBLUEX, BBLUEY);
	}
}

void ZerglingBlood::onReceiveText(BWAPI::Player* player, std::string text)
{
	Broodwar->printf("%s said '%s'", player->getName().c_str(), text.c_str());
}

void ZerglingBlood::onPlayerLeft(BWAPI::Player* player)
{
	Broodwar->printf("%s left the game.",player->getName().c_str());
}

void ZerglingBlood::onUnitDiscover(BWAPI::Unit* unit)
{
	/* if (!Broodwar->isReplay() && Broodwar->getFrameCount()>1)
	Broodwar->printf("A %s [%x] has been discovered at (%d,%d)",unit->getType().getName().c_str(),unit,unit->getPosition().x(),unit->getPosition().y());
	*/
	

}

void ZerglingBlood::onUnitEvade(BWAPI::Unit* unit)
{

	/*if (!Broodwar->isReplay() && Broodwar->getFrameCount()>1)
		Broodwar->printf("A %s [%x] was last accessible at (%d,%d)",unit->getType().getName().c_str(),unit,unit->getPosition().x(),unit->getPosition().y());
*/
}

void ZerglingBlood::onUnitShow(BWAPI::Unit* unit)
{
	if (Broodwar->getFrameCount()>1 && unit->getType().getID() != ZBLING)
	{
		Broodwar->printf("A %s [%x] has been found at (%d,%d)",unit->getType().getName().c_str(),unit,unit->getPosition().x(),unit->getPosition().y());
	}

	switch(unit->getType().getID())
	{
		case ZBDROPSHIP:
			stats[unit->getPlayer()->getColor()].spawn_location = unit->getPosition();
			attack_manager.foundDShip(unit);
			show_dship_pos = false;
			break;
		case ZBPROBE:
			stats[unit->getPlayer()->getColor()].probe_count++;
			Broodwar->printf("They now have %d probes", stats[unit->getPlayer()->getColor()].probe_count);
			break;
		case ZBHEROCREDIT:
			stats[unit->getPlayer()->getColor()].credit_count++;
			break;
	}
}

void ZerglingBlood::onUnitHide(BWAPI::Unit* unit)
{
	if(Broodwar->getFrameCount()>1 && unit->getType().getID() != ZBLING)
		Broodwar->printf("A %s [%x] was last seen at (%d,%d)",unit->getType().getName().c_str(),unit,unit->getPosition().x(),unit->getPosition().y());

	if(unit->getType().getID() == ZBDROPSHIP)
	{
		attack_manager.lostDShip(unit->getPosition(), Broodwar->getFrameCount());
		show_dship_pos = true;
	}
}

void ZerglingBlood::onUnitCreate(BWAPI::Unit* unit)
{
	if(unit->getPlayer() == drone->getPlayer())
	{
		switch(unit->getType().getID())
		{
			case ZBLING:
				switch(game_state)
				{
					case STARTUP:
					case PREMIDGAME:
						switch(set_scouts)
						{
							case 0:
								unit->move(Position(CHOKEBROWNCX, CHOKEBROWNCY));
								break;
							case 1:
								unit->move(Position(CHOKEORANGECX, CHOKEORANGECY));
								break;
							case 2:
								unit->move(Position(CHOKEPURPLECX, CHOKEPURPLECY));
								break;
							case 3:
								unit->move(Position(CHOKETEALCX, CHOKETEALCY));
								break;
							case 4:
								unit->move(Position(CHOKEBLUECX, CHOKEBLUECY));
								break;
							case 5:
								unit->move(Position(CHOKEREDCX, CHOKEREDCY));
								break;
							default:
								unit->move(Position(CENTERX, CENTERY));
						}
						if(set_scouts < 6)
						{
							scoutLings.insert(unit);
							++set_scouts;
							break;
						}
					case MIDGAME:
						std::set<Player*> players = Broodwar->getPlayers();
						for(std::set<Player*>::iterator it = players.begin(); it != players.end(); ++it)
						{
							Color player_color = (*it)->getColor();
							++stats[player_color].zergling_count;
						}
						stats[unit->getPlayer()->getColor()].spawn_location = unit->getPosition();
						if(squad_state == SURROUNDING)
						{
							squadLings.insert(unit);
							unit->attackMove(my_target);
						}
						else
							avaiLings.insert(unit);

						break;
				}
		}
	}
}


void ZerglingBlood::onUnitDestroy(BWAPI::Unit* unit)
{
	Color player_color = unit->getPlayer()->getColor();
	//if(isGamePlayer(player_color))
	//{
		switch(unit->getType().getID())
		{
			case ZBLING:
				--stats[player_color].zergling_count;
				break;
			case ZBPROBE:
				--stats[player_color].probe_count;
				break;
			case ZBHEROCREDIT:
				--stats[player_color].credit_count;
				int hero = hero_manager.whichHero(unit->getPosition());
				Broodwar->printf("THEY BOUGHT #%d", hero);
				break;
		}
			
		if(unit->getType().getID() == ZBLING)
		{
			//TODO support for more than 2 players
			std::set<Player* > players = Broodwar->getPlayers();
			if(drone->getPlayer() == unit->getPlayer())
			{
				for(std::set<Player* >::iterator it = players.begin(); it != players.end(); ++it)
				{
					if(drone->getPlayer() != (*it) && isGamePlayer((*it)->getColor()))
						++stats[(*it)->getColor()].kill_count;
				}
			}
			else
			{
				++stats[drone->getPlayer()->getColor()].kill_count;
			}
			
		}
	//}
}

void ZerglingBlood::drawStats()
{
	std::set<Unit*> myUnits = Broodwar->self()->getUnits();
	std::map<UnitType, int> unitTypeCounts;
	int id;
	for(std::set<Unit*>::iterator i = myUnits.begin(); i != myUnits.end(); i++)
	{
		//Ignore the following units
		id = (*i)->getType().getID();
		if(id == ZBMAPREVEALER || id == ZBDROPSHIP || id == ZBSCV || id == ZBDRONE)
			continue;
		if (unitTypeCounts.find((*i)->getType()) == unitTypeCounts.end())
		{
			unitTypeCounts.insert(std::make_pair((*i)->getType(),0));
		}
		unitTypeCounts.find((*i)->getType())->second++;
	}
	int line=0;
	for(std::map<UnitType,int>::iterator i=unitTypeCounts.begin();i!=unitTypeCounts.end();i++)
	{
		Broodwar->drawTextScreen(100,16*line,"- %d %ss",(*i).second, (*i).first.getName().c_str());
		line++;
	}
}

void ZerglingBlood::drawBullets()
{
	std::set<Bullet*> bullets = Broodwar->getBullets();
	for(std::set<Bullet*>::iterator i=bullets.begin();i!=bullets.end();i++)
	{
		Position p=(*i)->getPosition();
		double velocityX = (*i)->getVelocityX();
		double velocityY = (*i)->getVelocityY();
		if ((*i)->getPlayer()==Broodwar->self())
		{
			Broodwar->drawLineMap(p.x(),p.y(),p.x()+(int)velocityX,p.y()+(int)velocityY,Colors::Green);
			Broodwar->drawTextMap(p.x(),p.y(),"\x07%s",(*i)->getType().getName().c_str());
		}
		else
		{
			Broodwar->drawLineMap(p.x(),p.y(),p.x()+(int)velocityX,p.y()+(int)velocityY,Colors::Red);
			Broodwar->drawTextMap(p.x(),p.y(),"\x06%s",(*i)->getType().getName().c_str());
		}
	}
}

void ZerglingBlood::drawVisibilityData()
{
	for(int x=0;x<Broodwar->mapWidth();x++)
	{
		for(int y=0;y<Broodwar->mapHeight();y++)
		{
			if (Broodwar->isExplored(x,y))
			{
				if (Broodwar->isVisible(x,y))
					Broodwar->drawDotMap(x*32+16,y*32+16,Colors::Green);
				else
					Broodwar->drawDotMap(x*32+16,y*32+16,Colors::Blue);
			}
			else
				Broodwar->drawDotMap(x*32+16,y*32+16,Colors::Red);
		}
	}
}


void ZerglingBlood::showPlayers()
{
	std::set<Player*> players=Broodwar->getPlayers();
	for(std::set<Player*>::iterator i=players.begin();i!=players.end();i++)
	{
		Broodwar->printf("Player [%d]: %s is in force: %s",(*i)->getID(),(*i)->getName().c_str(), (*i)->getForce()->getName().c_str());
	}
}

void ZerglingBlood::showForces()
{
	std::set<Force*> forces=Broodwar->getForces();
	for(std::set<Force*>::iterator i=forces.begin();i!=forces.end();i++)
	{
		std::set<Player*> players=(*i)->getPlayers();
		Broodwar->printf("Force %s has the following players:",(*i)->getName().c_str());
		for(std::set<Player*>::iterator j=players.begin();j!=players.end();j++)
		{
			Broodwar->printf("  - Player [%d]: %s",(*j)->getID(),(*j)->getName().c_str());
		}
	}
}


/**
* Approximations based on the "start" of the choke, IE: the transistion to and from the bases.
* TOP LEFT: (995, 1375) to (1185, 1275)
* TOP RIGHT: (1665, 1310) to (1825, 1440)
* LEFT: (1150, 1950) to (1215, 2110)
* RIGHT: (1725, 1980) to (1725, 2175)
* BOTTOM LEFT: (915, 2580) to (1125, 2720)
* BOTTOM RIGHT: (1955, 2605) to (1755, 2689)
**/
void ZerglingBlood::drawChokes()
{
	Broodwar->drawLineMap(CHOKEREDX1,		CHOKEREDY1,		CHOKEREDX2,		CHOKEREDY2,		COLOR_RED);
	Broodwar->drawLineMap(CHOKEBLUEX1,		CHOKEBLUEY1,	CHOKEBLUEX2,	CHOKEBLUEY2,	COLOR_BLUE);
	Broodwar->drawLineMap(CHOKETEALX1,		CHOKETEALY1,	CHOKETEALX2,	CHOKETEALY2,	COLOR_TEAL);
	Broodwar->drawLineMap(CHOKEPURPLEX1,	CHOKEPURPLEY1,	CHOKEPURPLEX2,	CHOKEPURPLEY2,	COLOR_PURPLE);
	Broodwar->drawLineMap(CHOKEORANGEX1,	CHOKEORANGEY1,	CHOKEORANGEX2,	CHOKEORANGEY2,	COLOR_ORANGE);
	Broodwar->drawLineMap(CHOKEBROWNX1,		CHOKEBROWNY1,	CHOKEBROWNX2,	CHOKEBROWNY2,	COLOR_BROWN);

	Broodwar->drawCircleMap(CHOKEREDCX, CHOKEREDCY, CHOKEREDRAD, COLOR_RED);
	Broodwar->drawCircleMap(CHOKEBLUECX, CHOKEBLUECY, CHOKEBLUERAD, COLOR_BLUE);
	Broodwar->drawCircleMap(CHOKETEALCX, CHOKETEALCY, CHOKETEALRAD, COLOR_TEAL);
	Broodwar->drawCircleMap(CHOKEPURPLECX, CHOKEPURPLECY, CHOKEPURPLERAD, COLOR_PURPLE);
	Broodwar->drawCircleMap(CHOKEORANGECX, CHOKEORANGECY, CHOKEORANGERAD, COLOR_ORANGE);
	Broodwar->drawCircleMap(CHOKEBROWNCX, CHOKEBROWNCY, CHOKEBROWNRAD, COLOR_BROWN);
}

void ZerglingBlood::drawUnitPos()
{
	std::set<Unit*> myUnits = Broodwar->self()->getUnits();
	int id;
	for(std::set<Unit*>::iterator i = myUnits.begin(); i != myUnits.end(); i++)
	{
		id = (*i)->getType().getID();
		//Don't do anything with invisible sensors that are used to give vision in the
		//communal areas
		if(id == ZBMAPREVEALER)
			continue;
		Position pos = (*i)->getPosition();
		if(id != ZBLING)
		{
			Broodwar->drawTextMap(pos.x() ,pos.y() ,"\x10%d,%d",pos.x(),pos.y());
		}
	}
}


void ZerglingBlood::drawUnitID()
{
	std::set<Unit*> myUnits = Broodwar->self()->getUnits();
	int id;
	for(std::set<Unit*>::iterator i = myUnits.begin(); i != myUnits.end(); i++)
	{
		id = (*i)->getType().getID();
		//Don't do anything with invisible sensors that are used to give vision in the
		//communal areas
		if(id == ZBMAPREVEALER)
			continue;
		Position pos = (*i)->getPosition();
		if(id != ZBLING)
		{
			Broodwar->drawTextMap(pos.x() ,pos.y() ,"\x10%d", (*i)->getType().getID());
		}
	}
}

void ZerglingBlood::drawSquadCircle()
{
	Broodwar->drawCircle(CoordinateType::Map, squad.leader->getPosition().x(), squad.leader->getPosition().y(), squad.radius, drone->getPlayer()->getColor());
	Broodwar->drawCircle(CoordinateType::Map, squad.leader->getPosition().x(), squad.leader->getPosition().y(), squad.radius/2, drone->getPlayer()->getColor());
}


void ZerglingBlood::swapSpawn(int command)
{
	switch(command)
	{
		case BASE:
			switch(spawn_location)
			{
			case BWAITING:
			case BSPAWN:
			case DSPAWN:
			case SSPAWN:
			case BADJ:
				return;
			case SWAITING:
			case DWAITING:
			case SADJ:
			case DADJ:
				spawn_location = BSPAWN;
				drone->move(Position(Position(BASEX, BASEY)));
				return;
			}
		case SSHIP:
			switch(spawn_location)
			{
			case SWAITING:
			case BSPAWN:
			case DSPAWN:
			case SSPAWN:
				return;
			case BWAITING:
			case DWAITING:
			case BADJ:
			case SADJ:
			case DADJ:
				spawn_location = SSPAWN;
				drone->move(Position(Position(DROPSHIPX, DROPSHIPY)));
				return;
			}
		case DSHIP:
			switch(spawn_location)
			{
			case BSPAWN:
			case DSPAWN:
			case SSPAWN:
				return;
			case SWAITING:
				spawn_location = DADJ;
				drone->move(Position(Position(BASEX, BASEY)));
				return;
			case BWAITING:
			case DWAITING:
			case BADJ:
			case SADJ:
			case DADJ:
				spawn_location = DSPAWN;
				drone->move(Position(Position(DROPSHIPX, DROPSHIPY)));
				return;
			}
	}
}

void ZerglingBlood::checkSwap()
{
	Position pos = drone->getPosition();
	switch(spawn_location)
	{
	case BSPAWN:
		if(pos.x() >= BASEX - 50)
		{
			spawn_location = BADJ;
			drone->move(Position(Position(DROPSHIPX, DROPSHIPY)));
		}
		return;
	case DSPAWN:
		if(pos.x() < 1150)
		{
			spawn_location = DADJ;
			drone->move(Position(Position(BASEX, BASEY)));
		}
		return;
	case SSPAWN:
		if(pos.x() < 1290)
		{
			spawn_location = SWAITING;
		}
		return;
	case BADJ:
		if(pos.x() < 1290)
		{
			spawn_location = BWAITING;
			drone->stop();
		}
		return;
	case SADJ:
		if(pos.x() < 1250)
		{
			spawn_location = SWAITING;
			drone->stop();
		}
		return;
	case DADJ:
		if(pos.x() > 1290)
		{
			spawn_location = DWAITING;
			drone->stop();
		}
		return;
	}
}

bool ZerglingBlood::hasProbe(BWAPI::Color color)
{
	if(stats[color].probe_count > 0)
		return true;
	return false;
}

Position ZerglingBlood::getBase(BWAPI::Player * player)
{
        int player_color = player->getColor().getID();
        switch(player_color)
        {
                case IDRED:
                {
                        return Position(BREDX,BREDY);
                }
                case IDTEAL:
                {
                        return Position(BTEALX,BTEALY);
                }
                case IDBLUE:
                {
                        return Position(BBLUEX,BBLUEY);
                }
                case IDORANGE:
                {
                        return Position(BORANGEX,BORANGEY);
                }
                case IDBROWN:
                {
                        return Position(BBROWNX,BBROWNY);
                }
                case IDPURPLE:
                {
                        return Position(BPURPLEX,BPURPLEY);
                }
				default:
					return Position(0,0);
        }
}

void ZerglingBlood::checkHealth()
{
	for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
	{
			if((*it)->getHitPoints() < 30)
				(*it)->burrow();
	}
}

void ZerglingBlood::updateStats()
{
	//Update self

	if(spawn_location == SWAITING || spawn_location == BWAITING || spawn_location == DWAITING)
	{
		stats[drone->getPlayer()->getColor()].spawn_type = spawn_location;
	}

	std::set<Unit* > units = Broodwar->getAllUnits();
	for(std::set<Unit *>::iterator it = units.begin(); it != units.end(); ++it)
	{
		if((*it)->getType().getID() == ZBDRONE && (*it)->getPlayer() != drone->getPlayer())
		{
			Position drone_pos = (*it)->getPosition();
			if(drone_pos.x() < DROPSHIPX + 150)
			{
				stats[(*it)->getPlayer()->getColor()].spawn_type = SWAITING;
				stats[(*it)->getPlayer()->getColor()].spawn_location = Position(0,0);
			}
			else if(drone_pos.x() > BASEX - 500)
				stats[(*it)->getPlayer()->getColor()].spawn_type = BWAITING;
			else if(drone_pos.x() < BASEX - 500 && drone_pos.x() < DROPSHIPX + 150 )
			{
				if(stats[(*it)->getPlayer()->getColor()].spawn_type == SWAITING)
					stats[(*it)->getPlayer()->getColor()].spawn_type = DWAITING;
			}
		}
	}
}
void ZerglingBlood::printStats()
{
		std::set<Player*> players = Broodwar->getPlayers();
		for(std::set<Player*>::iterator it = players.begin(); it != players.end(); ++it)
		{
			Color player_color = (*it)->getColor();
			if(stats.count(player_color))
			{
				if(isGamePlayer(player_color))
				{
					Broodwar->printf("\x19Player_Color: %d has %d lings", player_color.getID(), stats[player_color].zergling_count);
					Broodwar->printf("\x19\t\t\t%d hero credits", stats[player_color].credit_count);
					Broodwar->printf("\x19\t\t\t%d kills", stats[player_color].kill_count);
					Broodwar->printf("\x19\t\t\t%d probes", stats[player_color].probe_count);
					Broodwar->printf("\x19\t\t\t%d spawnType", stats[player_color].spawn_type);
					Broodwar->printf("\x19""Dropship: [%d,%d]", stats[player_color].dropshipPos.x(),stats[player_color].dropshipPos.y());
					Broodwar->printf("\x19Spawn: [%d,%d]", stats[player_color].spawn_location.x() ,stats[player_color].spawn_location.y());
				}
			}
		}
}
void ZerglingBlood::checkScouts()
{
	for(std::set<Unit* >::iterator it = scoutLings.begin(); it != scoutLings.end(); ++it)
	{
		if((*it)->getPosition() == (*it)->getTargetPosition())
		{
			/*Broodwar->printf("CHECK");
			Broodwar->printf("Ordered   move  (%d,%d)",(*it)->getPosition().x(), (*it)->getPosition().y());
			Broodwar->printf("Unit's orderPos (%d,%d)",(*it)->getTargetPosition().x(),(*it)->getTargetPosition().y());
			Broodwar->printf("Unit's ID: %d",(*it)->getID());*/
			(*it)->burrow();
		}
	}
	int burrowed_zerglings = 0;
	for(std::set<Unit* >::iterator it = scoutLings.begin(); it != scoutLings.end() && burrowed_zerglings < 6; ++it)
	{
		if((*it)->isBurrowed())
			++burrowed_zerglings;
	}

	if(burrowed_zerglings == 6)
		++set_scouts;
}

void ZerglingBlood::groupMove(Position target)
{
	squad.target = target;
	squad.members = avaiLings;
	squad.leader = *squad.members.begin();
	squad.squadCount = avaiLings.size();
	squad.radius = squad.squadCount*8;
	show_squad_circle = true;
	for(std::set<Unit*>::iterator it = squad.members.begin(); it != squad.members.end(); ++ it)
	{
		(*it)->move(squad.target);
	}
	squad_state = MOVING;
}

void ZerglingBlood::groupAttack(Position target)
{
	attack_location = TOPRIGHT;
	groupMove(target);
}

void ZerglingBlood::checkMove()
{
	switch(squad_state)
	{
		case MOVING:
			if(squad.leader->getDistance(squad.target) <= squad.radius/2)
			{
				squad_state = WAITING;
				show_squad_circle = false;
				if(attack_location != NONE)
					startAttack(squad.target);
				return;
			}
			for(std::set<Unit*>::iterator it = squad.members.begin(); it != squad.members.end(); ++ it)
			{
				if((*it)->getDistance(squad.leader->getPosition()) > squad.radius)
				{
					squad_state = REGROUPING;
					squad.leader->stop();
					break;
				}
			}
			if(squad_state == REGROUPING)
			{
				for(std::set<Unit*>::iterator it = squad.members.begin(); it != squad.members.end(); ++ it)
					(*it)->move(squad.leader->getPosition());
			}
			break;
		case REGROUPING:
			for(std::set<Unit*>::iterator it = squad.members.begin(); it != squad.members.end(); ++ it)
			{
				if((*it)->getDistance(squad.leader->getPosition()) > squad.radius/2)
					return;
			}
			squad_state = MOVING;
			for(std::set<Unit*>::iterator it = squad.members.begin(); it != squad.members.end(); ++ it)
			{
				(*it)->move(squad.target);
			}
			break;
		case RETREATING:
			squad_state = WAITING;
			attack_location = NONE;
			break;
	}
}

void ZerglingBlood::checkAttack()
{
	if(hasProbe(Broodwar->enemy()->getColor()))
	{
		squad_state = RETREATING;
		for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
		{
			(*it)->move(Position(CENTERX, CENTERY));
		}
	}
}

void ZerglingBlood::startAttack(BWAPI::Position target)
{
	squad_state = ATTACKING;
	for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
	{
		(*it)->attackMove(target);
	}
}

void ZerglingBlood::surround(BWAPI::Position target, int radius)
{
	
	my_target = target;
	my_radius = radius;
	squad_state = SURROUNDING;
	for(std::set<Unit*>::iterator it = avaiLings.begin(); it != avaiLings.end(); ++ it)
	{
		(*it)->attackMove(target);
		squadLings.insert(*it);
		avaiLings.erase(*it);
	}
}

void ZerglingBlood::checkSurround()
{
	for(std::set<Unit*>::iterator it = squadLings.begin(); it != squadLings.end(); ++ it)
	{
		if((*it)->getDistance(my_target) <= my_radius)
		{
			(*it)->stop();
			avaiLings.insert(*it);
			squadLings.erase(*it);
		}
	}
}
